﻿using FreeSql;
using Masuit.Tools;
using Newtonsoft.Json;
using Simple.Contracts.Contracts;
using Simple.Contracts.Enums.Common;
using Simple.Contracts.Models;
using Simple.Contracts.Models.Common;
using Simple.Repository;
using Simple.Repository.SimpleEntitys;
using SKIT.FlurlHttpClient.Wechat.Api;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinUserInfoBatchGetRequest.Types;

namespace Simple.Services.Services
{
    /// <summary>
    /// 微信服务类
    /// </summary>
    public class WeChatService : BaseService, IWeChatService
    {
        private readonly IRedisService _redisService;
        private readonly Dictionary<WeChatAppClientEnum, WechatApiClient> _weChatAppClientDic;
        public WeChatService(Dictionary<WeChatAppClientEnum, WechatApiClient> weChatAppClientDic, IRedisService redisService, FreeSqlCloud freeSqlCloud, CurrentAccount currentAccount)
            : base(freeSqlCloud, currentAccount)
        {
            _weChatAppClientDic = weChatAppClientDic;
            _redisService = redisService;
        }

        /// <summary>
        /// 获取唯一访问凭证
        /// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
        /// </summary>
        /// <param name="weChatAppClient"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<string> GetAccessToken(WeChatAppClientEnum weChatAppClient)
        {
            var accessToken = _redisService.GetWechatAccessToken(weChatAppClient);
            if (string.IsNullOrEmpty(accessToken))
            {
                var client = _weChatAppClientDic[weChatAppClient];
                var res = await client.ExecuteCgibinTokenAsync(new SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinTokenRequest() { GrantType = "client_credential" });
                accessToken = res.AccessToken;
                _redisService.SetWechatAccessToken(weChatAppClient, accessToken, 7200 - 200);
            }
            return accessToken;
        }

        /// <summary>
        /// 登录凭证校验,获取openid和unionid
        /// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
        /// </summary>
        /// <param name="weChatAppClient"></param>
        /// <param name="js_code"></param>
        /// <returns></returns>
        public async Task<WeChatSessionDto> GetJScode2Session(WeChatAppClientEnum weChatAppClient, string js_code)
        {
            var accessToken = await GetAccessToken(weChatAppClient);
            var client = _weChatAppClientDic[weChatAppClient];
            var res = await client.ExecuteSnsJsCode2SessionAsync(new SKIT.FlurlHttpClient.Wechat.Api.Models.SnsJsCode2SessionRequest() { AccessToken = accessToken, GrantType = "authorization_code", JsCode = js_code });
            return new WeChatSessionDto() { OpenId = res.OpenId, UnionId = res.UnionId };
        }

        /// <summary>
        /// 恩睦照护小程序登录信息
        /// </summary>
        /// <param name="wechatUser"></param>
        /// <returns></returns>
        private async Task<WeChatZhaohuAppletLoginDto> GetWeChatZhaohuAppletLogin(WechatUser wechatUser)
        {
            var res = new WeChatZhaohuAppletLoginDto()
            {
                userSessionInfo = new WeChatSessionDto()
                {
                    NickName = wechatUser.NickName,
                    OpenId = wechatUser.WechatOpenIdZhaohuApplet,
                    UnionId = wechatUser.WechatUnionId
                },
                userToken = Guid.NewGuid().ToString("N"),
                userInfo = new CurrentAccount()
                {
                    CompanyId = 0,
                    CompanyName = string.Empty,
                    CompanyVersion = string.Empty,
                    CompanyVersionExpiryTime = DateTime.Now.AddYears(10),
                    EmployeeId = 0,
                    EmployeeIsAdmin = false,
                    EmployeeName = string.Empty,
                    EmployeePermissions = new List<string>(),
                    EmployeePhone = string.Empty,
                    EmployeeRoleIds = new List<long>(),
                }
            };
            var employee = await _simpleFreeSql.Select<Employee>().Where(x => x.Phone == wechatUser.Phone && x.IsDelete == 0 && x.Status == 1).FirstAsync();
            if (employee == null)
            {
                return res;
            }

            var company = await _simpleFreeSql.Select<Company>().Where(x => x.Id == employee.CompanyId && x.IsDelete == 0 && x.VersionExpiryTime > DateTime.Now).FirstAsync();
            if (company == null)
            {
                return res;
            }

            var employeePermissions = new List<string>();
            var employeeRoleIds = await _simpleFreeSql.Select<RoleEmployee>().Where(x => x.CompanyId == employee.CompanyId && x.EmployeeId == employee.Id && x.IsDelete == 0).ToListAsync(x => x.RoleId);
            if (employee.IsAdmin == 0)
            {
                var employeePermissionIds = await _simpleFreeSql.Select<RolePermission>().Where(x => x.CompanyId == employee.CompanyId && employeeRoleIds.Contains(x.RoleId) && x.IsDelete == 0).ToListAsync(x => x.PermissionId);
                employeePermissions = await _simpleFreeSql.Select<SysPermission>().Where(x => x.Version.Contains(company.Version + "√") && employeePermissionIds.Contains(x.Id)).ToListAsync(x => x.Name);
            }
            else
            {
                employeePermissions = await _simpleFreeSql.Select<SysPermission>().Where(x => x.Version.Contains(company.Version + "√")).ToListAsync(x => x.Name);
            }
            res.userInfo = new CurrentAccount()
            {
                CompanyId = employee.CompanyId,
                CompanyName = company.Name,
                CompanyVersion = company.Version,
                CompanyVersionExpiryTime = company.VersionExpiryTime,
                EmployeeId = employee.Id,
                EmployeeIsAdmin = employee.IsAdmin == 1,
                EmployeeName = employee.Name,
                EmployeePermissions = employeePermissions,
                EmployeePhone = employee.Phone,
                EmployeeRoleIds = employeeRoleIds,
            };
            _redisService.SetAccountLoginToken(res.userToken, JsonConvert.SerializeObject(res.userInfo), employee.CompanyId, employee.Id, 60 * 60 * 24 * 14);
            return res;
        }

        /// <summary>
        /// 恩睦照护小程序登录
        /// </summary>
        /// <param name="js_code"></param>
        /// <returns></returns>
        public async Task<Result<WeChatZhaohuAppletLoginDto>> WeChatZhaohuAppletLogin(string js_code)
        {
            var sessionInfo = await GetJScode2Session(WeChatAppClientEnum.AmosZhaoHuWechatApiClient, js_code);
            var wechatUser = await _simpleFreeSql.Select<WechatUser>().Where(x => x.WechatOpenIdZhaohuApplet == sessionInfo.OpenId).FirstAsync();
            if (wechatUser == null || wechatUser.Phone.IsNullOrEmpty())
            {
                var res = new WeChatZhaohuAppletLoginDto()
                {
                    userSessionInfo = sessionInfo,
                };
                return Result<WeChatZhaohuAppletLoginDto>.Success(res);
            }
            else
            {
                var res = await GetWeChatZhaohuAppletLogin(wechatUser);
                return Result<WeChatZhaohuAppletLoginDto>.Success(res);
            }
        }

        /// <summary>
        /// 恩睦照护小程序注册
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Result<WeChatZhaohuAppletLoginDto>> WeChatZhaohuAppletRegister(WeChatZhaohuAppletRegisterInput input)
        {
            var codeIsEffective = _redisService.CheckLoginCodeIsEffective(input.Phone, input.Code);
            if (!codeIsEffective)
            {
                return Result<WeChatZhaohuAppletLoginDto>.FriendlyReminder("验证码无效");
            }

            var wechatUser = await _simpleFreeSql.Select<WechatUser>().Where(x => x.WechatOpenIdZhaohuApplet == input.OpenId).FirstAsync();
            if (wechatUser == null)
            {
                wechatUser = new WechatUser()
                {
                    Phone = input.Phone,
                    NickName = input.NickName,
                    WechatUnionId = input.UnionId,
                    WechatOpenIdZhaohuApplet = input.OpenId,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                };
                wechatUser.Id = await _simpleFreeSql.Insert<WechatUser>(wechatUser).ExecuteIdentityAsync();
            }
            else
            {
                wechatUser.Phone = input.Phone;
                wechatUser.WechatUnionId = input.UnionId;
                wechatUser.WechatOpenIdZhaohuService = input.OpenId;
                wechatUser.UpdateTime = DateTime.Now;
                await _simpleFreeSql.Update<WechatUser>().SetSource(wechatUser).ExecuteAffrowsAsync();
            }

            var res = await GetWeChatZhaohuAppletLogin(wechatUser);
            return Result<WeChatZhaohuAppletLoginDto>.Success(res);
        }
    }
}